﻿using AutoMapper;
using DFGK.IRepository;
using DFGK.IService;
using DFGK_WMS.Model.Dto;
using DFGK_WMS.Model.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;

namespace DFGK.Service
{
    public class CellService : BaseService, ICellService
    {
        private readonly IWarehouseRepository _warehouseRepository;
        private readonly IAreaRepository _areaRepository;
        private readonly IShelfRepository _shelfRepository;
        private readonly ICellRepository _cellRepository;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IDictItemRepository _dictItemRepository;
        private readonly IRoutewayRepository _routewayRepository;
        public CellService(IMapper mapper, ICellRepository _cellRepository, IWarehouseRepository warehouseRepository, IAreaRepository areaRepository, IShelfRepository shelfRepository, IDictItemRepository _dictItemRepository, IUnitOfWork unitOfWork, IRoutewayRepository routewayRepository) : base(mapper)
        {
            this._cellRepository = _cellRepository;
            this._dictItemRepository = _dictItemRepository;
            _warehouseRepository = warehouseRepository;
            _areaRepository = areaRepository;
            _shelfRepository = shelfRepository;
            _unitOfWork = unitOfWork;
            _routewayRepository = routewayRepository;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool AddCell(Cell obj, out string message)
        {
            message = string.Empty;
            var cobj = _cellRepository.QueryIsEntityWhere(x => x.Code == obj.Code);
            if (cobj != null)
            {
                message = "编码已存在！";
                return false;
            }
            if (obj.WhId == null)
            {
                message = "请选择库房！";
                return false;
            }
            //库房
            var wobj = _warehouseRepository.QueryEntityById((long)obj.WhId);
            if (wobj != null && wobj.Status == 1)
            {
                obj.WhName = wobj.Name;
                obj.WhCode = wobj.Code;
            }
            else
            {
                message = "库房不存在或已被禁用！";
                return false;
            }
            if (obj.AreaId == null)
            {
                message = "请选择库区！";
                return false;
            }
            //库区
            var aobj = _areaRepository.QueryEntityById((long)obj.AreaId);
            if (aobj != null && aobj.Status == 1)
            {
                obj.AreaName = aobj.Name;
                obj.AreaCode = aobj.Code;
            }
            else
            {
                message = "库区不存在或已被禁用！";
                return false;
            }
            if (obj.ShelfId == null)
            {
                message = "请选择货架！";
                return false;
            }
            //货架
            var sobj = _shelfRepository.QueryEntityById((long)obj.ShelfId);
            if (sobj != null && sobj.Status == 1)
            {
                obj.ShelfCode = sobj.Code;
                obj.ShelfName = sobj.Name;
                obj.RoutewayId = sobj.RoutewayId.GetValueOrDefault();
            }
            else
            {
                message = "货架不存在或已被禁用！";
                return false;
            }
            obj.DistanceValue = Convert.ToDecimal(Math.Sqrt(Math.Pow(obj.LayerNo, 2) + Math.Pow(obj.ColumnNo, 2) + Math.Pow(obj.LineNo - 1, 2)));

            _cellRepository.AddEntity(obj);
            return _unitOfWork.SaveChangesEntity();
        }

        /// <summary>
        /// 批量添加仓位
        /// </summary>
        /// <param name="cellCreateBodyDTO"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool BatchCreateCell(CellCreateBodyDTO cellCreateBodyDTO, out string message)
        {
            message = "";
            List<Cell> cellList = new List<Cell>();
            var warehouse = _warehouseRepository.QueryIsEntityWhere(w => w.Id == cellCreateBodyDTO.WhId && w.Status == 1);
            if (warehouse == null)
            {
                message = "库房不存在或已被禁用！";
                return false;
            }
            var area = _areaRepository.QueryIsEntityWhere(a => a.Id == cellCreateBodyDTO.AreaId && a.Status == 1);
            if (area == null)
            {
                message = "库区不存在或已被禁用";
                return false;
            }
            List<Shelf> shelves = _shelfRepository.GetEntityWhereAll(s => s.WhId == cellCreateBodyDTO.WhId && s.AreaId == cellCreateBodyDTO.AreaId && s.Status == 1 && cellCreateBodyDTO.ShelfIds.Contains(s.Id)).ToList();
            if (shelves == null || shelves.Count == 0)
            {
                message = "货架不存在或已被禁用";
                return false;
            }
            var rlist = _routewayRepository.GetEntityAlls();
            foreach (var shelf in shelves)
            {
                int? rouway = rlist.FirstOrDefault(x => x.Id == shelf.RoutewayId)?.DisplayOrder;
                if (rouway <= 0 || rouway==null)
                {
                    message = "巷道信息有误！";
                    return false;
                }

                int maxDepth = shelf.Depth.GetValueOrDefault();

                for (int layerIndex = 1; layerIndex <= cellCreateBodyDTO.MaxLayer; layerIndex++)
                {
                    for (int columnIndex = 1; columnIndex <= cellCreateBodyDTO.MaxColumn; columnIndex++)
                    {
                        bool isMaxDepth=false;
                        if (shelf.DisplayOrder==1)
                        {
                            isMaxDepth = true;
                        }
                            string name = string.Format("{0}巷道{1}排{2}列{3}层{4}深位", rouway.ToString(), shelf.Number.ToString(), columnIndex.ToString(), layerIndex.ToString(), maxDepth.ToString());
                            string cellCode = string.Format("Cell:{0}_{1}_{2}_{3}_{4}", rouway.ToString(), shelf.Number, columnIndex.ToString(), layerIndex.ToString(), maxDepth.ToString());

                            Cell cell = new Cell
                            {
                                Id = YitIdHelper.NextId(),
                                Code = cellCode,
                                Name = name,
                                WhId = warehouse.Id,
                                WhName = warehouse.Name,
                                AreaId = area.Id,
                                AreaName = area.Name,
                                LineNo = shelf.Number ?? 0,
                                LayerNo = layerIndex,
                                ColumnNo = columnIndex,
                                DepthIndex = (int)shelf.Depth,
                                IsLock = false,
                                Status = 1,
                                IsMaxDepth = isMaxDepth,
                                FullStatus = 0,
                                BusinessType = 0,
                                RoutewayId = shelf.RoutewayId.GetValueOrDefault(),
                                CreateDate = DateTime.Now,
                                ShelfId = shelf.Id,
                                ShelfCode = shelf.Code,
                                ShelfName = shelf.Name,
                                CellType = 1,
                                DistanceValue = Convert.ToDecimal(Math.Sqrt(Math.Pow(layerIndex, 2) + Math.Pow(columnIndex, 2) + Math.Pow(layerIndex - 1, 2))),
                                HeightType = 1,
                                AreaCode = area.Code,
                                WhCode = warehouse.Code,
                            };
                            cellList.Add(cell);
                    }
                }
            }
            if (cellList == null || cellList.Count == 0)
            {
                return false;
            }
            _cellRepository.AddEntityList(cellList);
            if (_unitOfWork.SaveChangesEntity())
            {
                _unitOfWork.CommitChanges();
                return true;
            }
            _unitOfWork.RollbackChanges();
            return false;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool DelCell(long id)
        {
            var cobj = _cellRepository.QueryEntityById(id);
            if (cobj != null)
            {
                _cellRepository.DelEntity(cobj);
                return _unitOfWork.SaveChangesEntity();
            }
            return false;
        }

        public List<Cell> GetAllCellList()
        {
            return _cellRepository.GetAllEntityList();
        }

        public Cell? GetCellById(long id)
        {
            return _cellRepository.QueryEntityById(id);
        }

        /// <summary>
        /// 仓位统计
        /// </summary>
        /// <returns></returns>
        public CellStatisticsDto GetCellCount()
        {
            CellStatisticsDto celllist = new CellStatisticsDto();
            var cells = _cellRepository.GetEntityAlls();
            celllist.CellLock = cells.Where(x => x.Status == 2).Count().ToString();
            celllist.CellReserve = cells.Where(x => x.FullStatus == 0 && x.IsLock == false && x.BusinessType == 0 && x.Status == 1 && x.AreaCode.Contains("L")).Count().ToString();
            celllist.CellCount = cells.Count().ToString();
            celllist.CellUseCount = cells.Where(x => x.FullStatus == 1).Count().ToString();
            celllist.CellVacancyCount = cells.Where(x => x.FullStatus == 0).Count().ToString();
            return celllist;
        }

        public List<Cell> GetCellList(string? logicalPartCode, int fullStatus, int status, string? cname, long whid, long areid, long sheid, int pageIndex, int pageSize, out int totalCount)
        {
            var clist = _cellRepository.GetEntityAlls();
            //逻辑分区
            if (!string.IsNullOrEmpty(logicalPartCode))
            {
                clist = clist.Where(x => x.LogicalPartCode == logicalPartCode);
            }
            //仓位状态
            if (fullStatus < 3)
            {
                clist = clist.Where(x => x.FullStatus == fullStatus);
            }
            //状态
            if (status < 8)
            {
                clist = clist.Where(x => x.Status == status);
            }
            //仓位名称
            if (!string.IsNullOrEmpty(cname))
            {
                clist = clist.Where(x => x.Name.Contains(cname));
            }
            //库房
            if (whid != 0)
            {
                clist = clist.Where(x => x.WhId == whid);
            }
            //库区
            if (areid != 0)
            {
                clist = clist.Where(x => x.AreaId == areid);
            }
            //货架
            if (sheid != 0)
            {
                clist = clist.Where(x => x.ShelfId == sheid);
            }
            var list = _cellRepository.GetEntityAlls(clist, pageIndex, pageSize, out totalCount, x => x.CreateDate, false);
            return list.ToList();
        }

        /// <summary>
        /// 仓位左侧树形显示
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public List<Menuitem> GetMenuitem()
        {
            var wlist = _warehouseRepository.GetAllEntityList();

            return wlist.Select(item => new Menuitem
            {
                label = item.Name,
                value = item.Id,
                icon = item.Code,
                alias = "wh",
                children = GetAreaMenuitem(item.Id)
            }).ToList();
        }
        public List<Menuitem> GetAreaMenuitem(long wid)
        {
            var list = _areaRepository.GetEntityWhereAll(x => x.WhId == wid).ToList();
            return list.Select(x => new Menuitem
            {
                label = x.Name,
                value = x.Id,
                icon = x.Code,
                alias = "area",
                children = GetShelfMenuitem(x.Id)
            }).ToList();
        }
        public List<Menuitem> GetShelfMenuitem(long aid)
        {
            var list = _shelfRepository.GetEntityWhereAll(x => x.AreaId == aid);
            return list.Select(x => new Menuitem
            {
                label = x.Name,
                value = x.Id,
                icon = x.Code,
                alias = "shelf",
                children = null
            }).ToList();
        }

        /// <summary>
        /// 修改仓位
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool UpdCell(Cell obj, out string message)
        {
            message = string.Empty;
            var cobj = _cellRepository.QueryIsEntityWhere(x => x.Id != obj.Id && x.Code == obj.Code);
            if (cobj != null)
            {
                message = "编码已存在！";
                return false;
            }

            //库房
            var wobj = _warehouseRepository.QueryEntityById((long)obj.WhId);
            if (wobj != null && wobj.Status == 1)
            {
                obj.WhName = wobj.Name;
                obj.WhCode = wobj.Code;
            }
            else
            {
                message = "库房不存在或已被禁用！";
                return false;
            }
            if (obj.AreaId == null)
            {
                message = "请选择库区！";
                return false;
            }
            //库区
            var aobj = _areaRepository.QueryEntityById((long)obj.AreaId);
            if (aobj != null && aobj.Status == 1)
            {
                obj.AreaName = aobj.Name;
                obj.AreaCode = aobj.Code;
            }
            else
            {
                message = "库区不存在或已被禁用！";
                return false;
            }
            if (obj.ShelfId == null)
            {
                message = "请选择货架！";
                return false;
            }
            //货架
            var sobj = _shelfRepository.QueryEntityById((long)obj.ShelfId);
            if (sobj != null && sobj.Status == 1)
            {
                obj.ShelfCode = sobj.Code;
                obj.ShelfName = sobj.Name;
                obj.RoutewayId = sobj.RoutewayId.GetValueOrDefault();
            }
            else
            {
                message = "货架不存在或已被禁用！";
                return false;
            }
            obj.DistanceValue = Convert.ToDecimal(Math.Sqrt(Math.Pow(obj.LayerNo, 2) + Math.Pow(obj.ColumnNo, 2) + Math.Pow(obj.LineNo - 1, 2)));

            _cellRepository.UpdEntity(obj);
            return _unitOfWork.SaveChangesEntity();
        }

        public List<Cell> GetTransferBinToCellList(long id)
        {
            var clist = _cellRepository.GetEntityAlls();
            List<Cell> list = new List<Cell>();
            if(!clist.Any())
            {
                return list;
            }
            var cobj = _cellRepository.QueryEntityById(id);
            if (cobj == null || cobj.IsLock!=true)
            {
                return list;
            }
            var robj = _routewayRepository.QueryEntityById(cobj.RoutewayId ?? 0);
            if (robj == null || (robj != null && robj.Status != 1))
            {
                return list;
            }
            var aobj = _areaRepository.QueryEntityWhere(x => x.Code == cobj.AreaCode);
            if(aobj == null || (aobj != null && aobj.Status != 1))
            {
                return list;
            }
            var sobj = _shelfRepository.QueryEntityWhere(x => x.Code == cobj.ShelfCode);
            if (sobj == null || (sobj != null && sobj.Status != 1))
            {
                return list;
            }
            var rclist = clist.Where(x =>
            x.RoutewayId == cobj.RoutewayId &&
      x.IsLock == false || (x.IsLock == true && x.Code == "Cell:2_1_1_1_1") &&
      
      x.BusinessType == 0 || (x.BusinessType == 1 && x.Code == "Cell:2_1_1_1_1") &&
      x.FullStatus == 0 || (x.FullStatus == 1 && x.Code == "Cell:2_1_1_1_1") &&
      (x.Status == 1 || (x.Status == 2 && x.Code == "Cell:2_1_1_1_1"))
  );
            if (rclist.Any())
            {
                list = rclist.ToList();
                return list;
            }
            rclist = clist.Where(x => x.RoutewayId == cobj.RoutewayId && x.IsLock == false || (x.IsLock == true && x.Code == "Cell:2_1_1_1_1") &&  x.IsMaxDepth == false && x.BusinessType == 0 || (x.BusinessType == 1 && x.Code == "Cell:2_1_1_1_1") && x.FullStatus == 0 || (x.FullStatus == 1 && x.Code == "Cell:2_1_1_1_1") && ( x.Status == 1 || (x.Status==2 && x.Code== "Cell:2_1_1_1_1")));
            if (rclist.Any())
            {
                list = rclist.ToList();
                return list;
            }
            list.Clear();
            return list;
        }

        public Cell? GetCellByCode(string code)
        {
            var cobj = _cellRepository.QueryIsEntityWhere(x => x.Code == code);
            return cobj;
        }
    }
}
